package org.jmc.refmanager.web.wicket;

import org.apache.wicket.Page;
import org.apache.wicket.Response;
import org.apache.wicket.authentication.AuthenticatedWebApplication;
import org.apache.wicket.authentication.AuthenticatedWebSession;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.pages.PageExpiredErrorPage;
import org.apache.wicket.protocol.http.WebRequest;
import org.apache.wicket.protocol.http.WebRequestCycle;
import org.apache.wicket.protocol.http.WebRequestCycleProcessor;
import org.apache.wicket.protocol.http.request.CryptedUrlWebRequestCodingStrategy;
import org.apache.wicket.protocol.http.request.WebRequestCodingStrategy;
import org.apache.wicket.request.IRequestCodingStrategy;
import org.apache.wicket.request.IRequestCycleProcessor;
import org.apache.wicket.request.target.coding.QueryStringUrlCodingStrategy;
import org.apache.wicket.spring.injection.annot.SpringComponentInjector;
import org.jmc.refmanager.util.LoggingUtils;
import org.jmc.refmanager.web.wicket.page.HomePage;
import org.jmc.refmanager.web.wicket.page.SignInPage;
import org.jmc.refmanager.web.wicket.page.error.ForbiddenErrorPage;
import org.jmc.refmanager.web.wicket.page.error.InternalServerErrorPage;
import org.jmc.refmanager.web.wicket.page.error.NotFoundErrorPage;
import org.jmc.refmanager.web.wicket.page.service.OrgUnitJsonProviderPage;
import org.jmc.refmanager.web.wicket.security.RefManagerAuthenticatedWebSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RefManagerApplication extends AuthenticatedWebApplication  {
	private final static String DEV = "development";
    private static final Logger logger = LoggerFactory.getLogger(WebRequestCycle.class);
	
	@Override
	protected void init() {
		super.init();
		mountBookmarkablePage("browse", OrgUnitJsonProviderPage.class);
		mount(new QueryStringUrlCodingStrategy("error/403", ForbiddenErrorPage.class));
		mount(new QueryStringUrlCodingStrategy("error/404", NotFoundErrorPage.class));
		mount(new QueryStringUrlCodingStrategy("error/500", InternalServerErrorPage.class));

		addComponentInstantiationListener(new SpringComponentInjector(this));
		
		// Can be enabled/disabled to leave 'wicket' XHTML extensions in
		// rendered result to browser (a development assistance setting)
		super.getMarkupSettings().setStripWicketTags(!isInDevConfigurationType());
		
        // Configure error pages
        getApplicationSettings().setPageExpiredErrorPage(getHomePage());
        getApplicationSettings().setAccessDeniedPage(ForbiddenErrorPage.class);
        getApplicationSettings().setInternalErrorPage(InternalServerErrorPage.class);
        getApplicationSettings().setPageExpiredErrorPage(PageExpiredErrorPage.class);
	}

	@Override
	public Class<? extends Page> getHomePage() {
		return HomePage.class;
	}

	@Override
	protected Class<? extends WebPage> getSignInPageClass() {
		return SignInPage.class;
	}

	@Override
	protected Class<? extends AuthenticatedWebSession> getWebSessionClass() {
		return RefManagerAuthenticatedWebSession.class;
	}

    /**
     * Returns our custom {@link WicketRequestCycle}.
     */
    @Override
    public WebRequestCycle newRequestCycle(org.apache.wicket.Request request, Response response) {
        //return new WicketRequestCycle(this, (WebRequest) request, response);
    	return new WebRequestCycle(this, (WebRequest) request, response) {
    		@Override
    		protected void logRuntimeException(RuntimeException e) {
    			LoggingUtils.logRuntimeException(logger, e);
    		}
    	};
    }

	@Override
	protected IRequestCycleProcessor newRequestCycleProcessor() {
		return new WebRequestCycleProcessor() {
			@Override
			protected IRequestCodingStrategy newRequestCodingStrategy() {
				if (isInDevConfigurationType()) {
					return new WebRequestCodingStrategy();
				} else {
					// Crypte les URLs les parametres ne sont pas visibles
					return new CryptedUrlWebRequestCodingStrategy(new WebRequestCodingStrategy());
				}
			}
		};
	}

	/*
	 * Indicate if configurationType defined in web.xml or via
	 * system property is equals to <code>development</code>.
	 * @return <code>true</code> if so.
	 */
	private boolean isInDevConfigurationType() {
		return this.getConfigurationType().equalsIgnoreCase(DEV);
	}
}
